#include "bga/graphics/TextureObject.h"

namespace bga {

TextureObject::TextureObject() : GLObject()
{
    /// generate object id
    this->id = generate();

    this->internalFormat = GL_RGBA;
    this->dataFormat = GL_RGBA;
    this->dataType = GL_UNSIGNED_BYTE;
    this->allocated = false;
    this->imageLoaded = false;
}

TextureObject::~TextureObject()
{
    glDeleteTextures(1, &(this->id));
}

void TextureObject::bind() const
{
    glBindTexture(this->target, this->id);
}

void TextureObject::unbind() const
{
    glBindTexture(this->target, 0);
}

void TextureObject::setImage(const std::string& filename)
{
    unsigned int maxImage = 1;
    if (this->target == GL_TEXTURE_CUBE_MAP)
    {
        maxImage = 6;
    }
    if (this->imageFilenameList.size() > maxImage)
    {
        imageFilenameList.clear();
    }
    /// push image filename
    this->imageFilenameList.push_back(filename);

    /// image has changed, reset flags
    this->allocated = false;
    this->imageLoaded = false;
}

void TextureObject::setWrapS(GLint wrap)
{
    this->wrapS = wrap;
}

GLint TextureObject::getWrapS() const
{
    return this->wrapS;
}

void TextureObject::setWrapT(GLint wrap)
{
    this->wrapT = wrap;
}

GLint TextureObject::getWrapT() const
{
    return this->wrapT;
}

void TextureObject::setWrapR(GLint wrap)
{
    this->wrapR = wrap;
}

GLint TextureObject::getWrapR() const
{
    return this->wrapR;
}

void TextureObject::setMinFilter(GLint minFilter)
{
    this->minFilter = minFilter;
}

GLint TextureObject::getMinFilter() const
{
    return this->minFilter;
}

void TextureObject::setMagFilter(GLint magFilter)
{
    this->magFilter = magFilter;
}

GLint TextureObject::getMagFilter() const
{
    return this->magFilter;
}

void TextureObject::setInternalFormat(GLint internalFormat)
{
    this->internalFormat = internalFormat;
}

GLint TextureObject::getInternalFormat() const
{
    return this->internalFormat;
}

void TextureObject::setDataFormat(GLenum dataFormat)
{
    this->dataFormat = dataFormat;
}

GLenum TextureObject::getDataFormat() const
{
    return this->dataFormat;
}

void TextureObject::setDataType(GLenum dataType)
{
    this->dataType = dataType;
}

GLenum TextureObject::getDataType() const
{
    return this->dataType;
}

bool TextureObject::isAllocated() const
{
    return this->allocated;
}

bool TextureObject::isImageLoaded() const
{
    return this->imageLoaded;
}

void TextureObject::applyParameters()
{
    glTexParameteri(this->target, GL_TEXTURE_WRAP_S, this->wrapS);
    glTexParameteri(this->target, GL_TEXTURE_WRAP_T, this->wrapT);
    if (target == GL_TEXTURE_3D)
    {
        glTexParameteri(this->target, GL_TEXTURE_WRAP_T, this->wrapR);
    }
    glTexParameteri(this->target, GL_TEXTURE_MIN_FILTER, this->minFilter);
    glTexParameteri(this->target, GL_TEXTURE_MAG_FILTER, this->magFilter);
}

void TextureObject::setActiveUnit(int unit)
{
    glActiveTexture(GL_TEXTURE0+unit);
}

GLuint TextureObject::generate() const
{
    GLuint id;
    glGenTextures(1, &id);
    return id;
}

}
